在 React 中,我們經常使用 useState
來管理組件的狀態,並讓組件隨著狀態的變化重新渲染。不過在某些情況,不希望狀態變更時觸發重新渲染,這時就可以使用 useRef
來保存狀態,或是引用 DOM 元素來操作。
useRef
基本語法當你呼叫 useRef
時,它會回傳一個包含 current
屬性的物件。這個 current
可以用來保存我們想要記住的值,且不會隨著重新渲染而丟失。
const ref = useRef(initialValue);
initialValue
是用來設定 current
的初始值。useRef
返回的物件(ref
)中的 current
屬性會保存這個值。useRef
的使用時機當我們需要在 React 中保存某些資料,但不希望資料變更時觸發組件的重新渲染,可以使用 useRef
。一個常見的例子是儲存表單中的輸入值,或是在某個事件觸發時保存資料,這些資料不會影響畫面的顯示。
useRef
也可以用來存取 DOM 元素的引用。在 React 中,很少直接操作 DOM 元素,例如用document.querySelector
的方式取得DOM,但在某些情況下,操作 DOM 是會需要用到的。例如,當需要聚焦到某個表單輸入欄位,或滾動到特定位置時,可以使用 useRef
來存取該元素的 DOM 引用。
useRef
保存狀態useState
每次變更狀態時,會觸發重新渲染組件,但有些狀態我們並不想讓它引發重新渲染。使用 useRef
可以避免這個問題。
範例:用 useRef
來實作一個不會觸發重新渲染的計數器:
import React, { useRef, useState } from 'react';
function Counter() {
const countRef = useRef(0); // 使用 useRef 保存計數器值
const [renderCount, setRenderCount] = useState(0); // 控制組件重新渲染的狀態
const incrementCount = () => {
countRef.current += 1; // 使用 useRef 的 current 更新計數器值
console.log("計數器值:", countRef.current);
};
return (
<div>
<p>計數器值不會觸發重新渲染: {countRef.current}</p>
<p>畫面重新渲染次數: {renderCount}</p>
<button onClick={incrementCount}>增加計數器值</button>
<button onClick={() => setRenderCount(renderCount + 1)}>強制重新渲染</button>
</div>
);
}
export default Counter;
在這個範例中,countRef
儲存了計數器的值,但它並不會觸發重新渲染。即便點擊「增加計數器值」按鈕,畫面顯示的數值也不會變動;要強制重新渲染,則可以點擊「強制重新渲染」按鈕。這顯示了 useRef
不會觸發重新渲染的特性。
當按下七次計數器之後,只有在 console.log 上顯示,畫面卻沒有更新。
但用 useState 的值更新後,countRef 的值就會被更新到畫面上。
useRef
存取 DOM 元素useRef
的另一個常見用途是直接存取 DOM 元素。我們可以用 useRef
來引用 HTML 元素,並進行聚焦、滾動等 DOM 操作。
當組件渲染後,我們可以使用 useRef
來讓一個輸入框自動獲得焦點。
import React, { useRef, useEffect } from 'react';
function AutoFocusInput() {
const inputRef = useRef(null); // 使用 useRef 來引用 DOM 元素
useEffect(() => {
inputRef.current.focus(); // 當組件渲染後,讓輸入框自動獲得焦點
}, []);
return (
<div>
<input ref={inputRef} placeholder="自動聚焦的輸入框" />
</div>
);
}
export default AutoFocusInput;
在這個範例中,我們使用了 inputRef
來引用輸入框,並在 useEffect
中讓這個輸入框在組件渲染後自動獲得焦點。這就是操作 DOM 元素的典型用法。
useRef
能夠幫助我們:
useRef
提供了方便的引用方式。與 useState
不同,useRef
不會觸發組件的重新渲染。當我們需要記住一些資料而不影響 UI 的時,useRef
是一個理想的選擇。另外再需要操作 DOM 元素時也能應用到。
本文將會同步更新到我的部落格